package com.mall.shop.controller;

import com.mall.shop.constants.SmsConstrant;
import com.mall.shop.dto.auth.LoginDto;
import com.mall.shop.dto.auth.RegisterDto;
import com.mall.shop.feign.thirdparty.ThirdPartyFeignService;
import com.mall.shop.service.AuthService;
import com.mall.shop.utils.R;
import com.mall.shop.vo.auth.UserInfoVO;
import com.xkcoding.justauth.AuthRequestFactory;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/auth")
public class AuthController {

    @Autowired
    private AuthService authService;
    @Autowired
    private ThirdPartyFeignService thirdPartyFeignService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AuthRequestFactory factory;

    @PostMapping("/sendSms")
    public R<String> sendSms(@RequestBody String mobile) {
        // 接口防刷，防止同一手机号在60秒内多次重复发送
        Long expireTime = stringRedisTemplate.opsForValue().getOperations().getExpire(SmsConstrant.SMS_CODE_CACHE_PREFIX + mobile, TimeUnit.MINUTES);
        if (Objects.nonNull(expireTime) && expireTime >= 1) {
            return R.failed("验证码发送过于频繁");
        }

        return thirdPartyFeignService.sendSms(mobile);
    }

    /**
     * 通过手机号和验证码登录
     * @param loginDto 登录参数
     * @return 用户信息
     */
    @PostMapping("/loginByMobile")
    public R<UserInfoVO> loginByMobile(@RequestBody @Valid LoginDto loginDto) {
        UserInfoVO userInfoVO = authService.loginByMobile(loginDto);
        return R.ok(userInfoVO);
    }

    /**
     * 用户注册
     * @param registerDto 注册信息
     * @return 注册结果
     */
    @PostMapping("/register")
    public R<Boolean> register(@RequestBody @Valid RegisterDto registerDto) {
        Boolean result = authService.register(registerDto);
        return R.ok(result);
    }

    /**
     * 三方授权登录
     * @param type 第三方标识
     * @param response 响应信息
     * @throws IOException 异常
     */
    @GetMapping("/login/{type}")
    public void loginBySource(@PathVariable String type, HttpServletResponse response) throws IOException {
        AuthRequest authRequest = factory.get(type);
        String redirectUrl = authRequest.authorize(AuthStateUtils.createState());
        response.sendRedirect(redirectUrl);
    }

    /**
     * 授权回调
     * @param type 第三方标识
     * @param callback 回调关键信息
     * @return 用户信息
     */
    @GetMapping("/{type}/callback")
    public R<Object> callBack(@PathVariable String type, AuthCallback callback) {
        AuthRequest authRequest = factory.get(type);
        AuthResponse response = authRequest.login(callback);
        // TODO 从response中封装UserInfoVO用户信息，然后返回给前端
        return R.ok(response.getData());
    }

    @GetMapping("/index")
    public String testDemo() {
        return "hello world";
    }

}
